Building Web Apps
Stream agent events to web, mobile, and desktop apps via Server-Sent Events (SSE)
HPD-Agent works in web applications through Server-Sent Events (SSE), enabling real-time streaming to React, Vue, Angular, mobile apps, and any HTTP client. The framework provides serialization tools for C# backends and a TypeScript client for frontends.
Architecture Overview
┌─────────────────┐ ┌─────────────────┐
│ Frontend │ SSE → │ ASP.NET API │
│ (TypeScript) │ ← HTTP │ (C# Backend) │
└─────────────────┘ └─────────────────┘
↓ ↓
React/Vue/etc. Agent.RunAsync()How it works:
- Frontend sends user messages via POST
- Backend streams agent events via SSE (text/event-stream)
- Frontend receives events in real-time using
hpd-agent-client - Bidirectional events (permissions, clarifications) are sent back via POST
Quick Start
1. Backend: ASP.NET Endpoint
Install the package:
dotnet add package HPD.AgentCreate a minimal SSE endpoint:
using HPD.Agent;
using HPD.Agent.Serialization;
var builder = WebApplication.CreateSlimBuilder(args);
var app = builder.Build();
app.MapPost("/agent/stream", async (
HttpContext context,
MessageRequest request) =>
{
var agent = new AgentBuilder()
.WithProvider("anthropic", "claude-sonnet-4-5")
.WithSystemInstructions("You are a helpful assistant.")
.Build();
context.Response.ContentType = "text/event-stream";
var writer = new StreamWriter(context.Response.Body);
await foreach (var evt in agent.RunAsync(request.Messages))
{
// Serialize event to JSON
var json = AgentEventSerializer.ToJson(evt);
// Send as SSE
await writer.WriteAsync($"data: {json}\n\n");
await writer.FlushAsync();
}
});
app.Run();
// Request model
record MessageRequest(List<ChatMessage> Messages);2. Frontend: TypeScript Client
Install the client:
npm install hpd-agent-clientCreate a React hook (or similar pattern for other frameworks):
import { useAgent } from 'hpd-agent-client/react';
function ChatComponent() {
const { messages, sendMessage, isStreaming } = useAgent({
conversationId: 'my-conversation',
baseUrl: 'http://localhost:5000'
});
const handleSubmit = (text: string) => {
sendMessage({ role: 'user', content: text });
};
return (
<div>
{messages.map((msg, i) => (
<div key={i}>{msg.content}</div>
))}
{isStreaming && <div>Agent is typing...</div>}
<input onSubmit={handleSubmit} />
</div>
);
}That's it! The client handles event parsing, message accumulation, and state management automatically.
What You Get
This minimal setup provides:
- Real-time text streaming
- Tool execution visibility
- Automatic message accumulation
- Turn lifecycle tracking
- Error handling
Production Setup
The quick start works for simple apps, but production deployments need:
- Conversation persistence - Save/restore conversations across sessions
- Permission prompts - UI dialogs for user approval
- Client-side tools - Execute tools in the browser (file pickers, geolocation, etc.)
- Cancellation - Stop button to interrupt long-running operations
- Error recovery - Retry logic, connection recovery
For complete production patterns, see:
- Event Handling - Understanding the event stream
- Bidirectional Events - User prompts and permissions
- Streaming & Cancellation - Stop button implementation
- Client Tools - Browser-side tool execution
Client Installation Options
The TypeScript client supports multiple frameworks:
# React (with hooks)
npm install hpd-agent-client
# Vue/Angular/Vanilla JS (core only)
npm install hpd-agent-clientAll frameworks use the same core client with framework-specific adapters.
See Also
- Event Handling - Understanding the event stream
- Building Console Apps - Native .NET console patterns